#pragma once
#include <Queue>
#include <mutex>
#include <thread>

template <typename T>
class SafeQueue
{
private:
    std::queue<T> _queue;
    std::mutex _mutex;
public:
    SafeQueue(){};
    ~SafeQueue(){};

    bool empty(){
        std::lock_guard<std::mutex> lock(_mutex);
        return _queue.empty();
    };
    int size(){
        std::lock_guard<std::mutex> lock(_mutex);
        return _queue.size();
    };
    
    T& front(){
        std::lock_guard<std::mutex> lock(_mutex);
        return _queue.front();
    }


    void push(T &t){
        std::lock_guard<std::mutex> lock(_mutex);
        _queue.emplace(t);
    };

    bool pop(){
        std::lock_guard<std::mutex> lock(_mutex);
        if(_queue.empty())
            return false;
        _queue.pop();
        return true;
    }

    T& Getfront()
    {
        std::unique_lock<std::mutex> lock(_mutex);
            // Block until the queue is not empty
        while (_queue.empty())
        {
            lock.unlock();
            std::this_thread::yield(); // Yield control to other threads
            lock.lock();
        }
        return _queue.front();
    }
    

};



